package base.reflection_demo.demo_01;

import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

/**
 * 通过反射API动态的操作：构造器、方法、属性
 * https://www.jianshu.com/p/3ea4a6b57f87
 */
@Slf4j
public class UserReflectionDemo1 {
    public static void main(String[] args) throws Exception {
        String path = "base.reflection_demo.demo_01.User";
        test1(path);
    }

    public static void test1(String path) throws Exception {
        Class<User> clazz = (Class<User>) Class.forName(path);
        //1.通过反射API操作构造方法
        //其实是调用了User的无参构造方法
        User user = clazz.newInstance();
        log.info("1 -> {}", user);

        /**
         * clazz.getConstructors()：只能获取所有公有构造方法
         * clazz.getDeclaredConstructors()：获取所有的构造方法(包括：私有、受保护、默认、公有)
         *
         * clazz.getConstructor(null)：获取公有、无参的构造方法
         * clazz.getDeclaredConstructor(float.class)：获取入参是float类型构造方法，不限定是否公有私有
         */
        // 获取带参构造方法
        Constructor<User> constructor = clazz.getDeclaredConstructor(int.class, int.class, String.class);
        User user1 = constructor.newInstance(1000, 18, "张三");
        log.info("2 -> {}", user1);

        //2.通过反射API操作普通方法
        User user2 = clazz.newInstance();
        Method setUname = clazz.getDeclaredMethod("setUname", String.class);
        setUname.setAccessible(true);
        setUname.invoke(user2, "李四");

        Method getUname = clazz.getDeclaredMethod("getUname", null);
        getUname.setAccessible(true);
        String name = (String) getUname.invoke(user2, null);
        log.info("3 -> {}", name);


        //3.通过反射API操作属性
        User user3 = clazz.newInstance();
        Field field = clazz.getDeclaredField("uname");
        field.setAccessible(true);
        field.set(user3, "王五");// 通过反射给user3设置uname值
        System.out.println(user3.getUname());

        log.info("4 -> {}", field.get(user3));// 通过反射获取user3的uname值
    }
}
